supce's blog

CSS Secret 读书笔记之伪随机背景&图像边框


伪随机背景

伪随机背景其实还是对条纹背景的扩展。假设一种场景,我们想得到不同颜色和不同宽度的垂直条纹。并且在背景平铺时不会产生接缝。利用linear-gradient好像可以轻松实现

<div class="rb-a"></div>
body{
    display: flex;
    flex-flow: row wrap;
    justify-content: space-around;
}
div{
    margin: 20px 20px;
    padding: 0;
    min-width: 20em;
    min-height: 6em;
}
.rb-a{
    background: linear-gradient(90deg,#fb3 15%,#655 0,#655 40%,#ab4 0,#ab4 65%,hsl(20,40%,90%) 0);
    background-size: 80px 100%;
}


从效果图中可以看出这个背景图的重复规律非常明显,每水平80px就会重复一次。
这时候可以考虑另一种思路:
把这组条纹从一个平面图拆散为多个图层,一种颜色作为底色,另外三种颜色作为条纹,然后再让条纹以不同的间隔进行重复平铺,同时利用background-size控制条纹的间距。

background: hsl(20,40%,90%);
background-image: linear-gradient(90deg,#fb3 10px,transparent 0),
                  linear-gradient(90deg,#ab4 20px,transparent 0),
                  linear-gradient(90deg,#655 20px,transparent 0);
background-size: 80px 100%,60px 100%,40px 100%;


随机的效果好了很多,但是仔细观察会发现每隔240px像素就会重复一次,且240正好是40 60 80 的最小公倍数。
如果我们将背景的宽度设置为质数,那么它们的最小公倍数就会很大,当大于屏幕宽度时就可以在视觉上满足随机背景了。于是将背景的宽度修改一下

background: hsl(20,40%,90%);
background-image: linear-gradient(90deg,#fb3 11px,transparent 0),
                  linear-gradient(90deg,#ab4 23px,transparent 0),
                  linear-gradient(90deg,#655 41px,transparent 0);
background-size: 41px 100%,61px 100%,83px 100%;


这时候的最小公倍数为416183=207583,已经可以满足我们的需求了。


图像边框

图片经常作为容器的背景,但是有时候想把一副图片作为边框。也就是说一张图片被剪裁到边框所在的方形环状区域。同时,也希望图片能够随着元素的大小进行缩放并完整的覆盖边框的区域。
但是border-image是一种九宫格伸缩法,将图片裁剪为九块,放到边框所对应的变和角,显然是不符合我们的要求的。
可以尝试设置元素的背景色为白色,然后给元素外部嵌套一个父元素,并设置背景为图片。

<div class="border-test">
    <div>this is a testthis is a testthis is a test
    this is a testthis is a testthis is a testthis is a test</div>
</div>
.border-test{
    background: url(stone-art.jpg);
    background-size: cover;
    padding: .5em;
}
.border-test > div{
    background: white;
    padding: 1em;
}

效果如下:

在强迫症的作用下,并不想嵌套一个父元素,就得换一个思路了。
首先设置元素的背景为图片,然后在背景图之上叠加一层纯色的实色背景。设置背景边框为透明,并且为两层背景指定不同的background-clip的值。由于只能在多重背景的最底层设置背景色,因此需要用一道从白色过渡到白色的CSS渐变来模拟出纯白色背景的效果。

<div class="border-a">this is a testthis is a testthis is a testthis is a testthis is a testthis is a testthis is a test</div>
.border-a,.border-b{
    max-width: 20em;
    max-height: 10em;
    padding: 1em;
    border: 1em solid transparent;
}
.border-a{
    background: linear-gradient(white,white),
                url(stone-art.jpg);
    background-size: cover; 
    background-clip: padding-box,border-box;
}


background-origin 属性规定 background-position 属性相对于什么位置来定位。其默认值为padding-box,因此边框的图片出现了奇怪的拼接效果。于是添加一条属性:
background-origin: border-box;
就可以到达下面这个结果了:

既然可以使用渐变那就可以模拟更多的边框效果了~ 比如下面这种:

background: linear-gradient(white,white) padding-box,
                repeating-linear-gradient(-45deg,red 0,red 12.5%,transparent 0,transparent 25%,#58a 0,
                    #58a 37.5%,transparent 0,transparent 50%) 0 0 / 4em 4em;

一种漂亮的信封效果:

当然,也可以给边框添加动画。

@keyframes ants {to {background-position: 100%}}
.border-c{
    border: 1px solid transparent;
    background: linear-gradient(white,white) padding-box,
                repeating-linear-gradient(-45deg,black 0,black 25%,white 0,white 50%) 0 0 / .6em .6em;
    animation: ants 12s ease-out infinite;
}


可惜图片看不出动画效果了。